#include "header.h"

int number = 0;//在线人数
int flg = 0; //私聊标志,置1为私聊

user_t client_ids[20] = {0};// 客户端数组 , 20个用户

int main(int argc, char const *argv[])
{
    if (3 != argc)
    {
        printf("格式: %s IP地址 端口号\n" , argv[0]);
        exit(-1);
    }
    // 建立连接
    int soc_fd = TCP_Init_Sever( atoi(argv[2]) , argv[1] );

    /******* 4等待响应 *********/
    struct sockaddr_in IPV4_client;  // 客户端的ip和端口
    socklen_t IPV4_len = sizeof(IPV4_client);

    pthread_t tid = 0;
    while (1)
    {
        int client_id = accept(soc_fd , (struct sockaddr*)&IPV4_client , &IPV4_len);//每连接一个客户端，会有新的套接字，开新的线程处理该次连接
        /****** 5处理通讯 ******/
        if(client_id > 0)
        {
            for (int i = 0; i < 20; i++)
            {
                if(client_ids[i].cid == 0)
                {
                    client_ids[i].cid = client_id; // 把客户端套接字存入顺序表
                    printf("[%s:%d]连接到服务器..\n",inet_ntoa(IPV4_client.sin_addr),ntohs(IPV4_client.sin_port));
                    break;
                }
            }
            /*****      多线程处理    *******/
            pthread_create(&tid,NULL,pthread_func,&client_id);
            pthread_detach(tid);
            // /***** 查看数组中是否出现重复的 套接字ID *****/
            // printf("已经加入到聊天室的套接字:");
            // for(int i = 0; i < 20 ;i++)
            // {
            //     printf("%d,",client_ids[i].cid);
            // }
            // printf("\n");
        }

    }      

    // 关闭连接
    close(soc_fd); 

    return 0;
}



void mass_send(char *sendbuf) // 转发给所有人
{
    for (int i = 0; i < 20; i++)
    {
        if (client_ids[i].cid > 0)
        {
            send(client_ids[i].cid,sendbuf,strlen(sendbuf),0);//发送包装好的的信息
        }
    }
    //记录聊天记录
    int fd = open("chat.txt",O_RDWR | O_CREAT | O_APPEND ,0666);//创建追加写
    write(fd,sendbuf,strlen(sendbuf));
    close(fd);
}

void user_add(int cid , char* name , char* pas1)  // 添加用户信息
{
    for(int i = 0;i < 20;i++)
    {
        if(client_ids[i].cid == cid)  // 通过套接字找相应的客户端
        {
            strcpy(client_ids[i].name , name);  // 添加名字
            strcpy(client_ids[i].pas , pas1);  // 添加密码
            break;
        }
    }
}


//子线程
void * pthread_func(void * arg)
{
    number++;
    printf("在线人数:%d\n" , number);

    //取出套接字cid
    int client_id = *(int*)arg;

    // 定义接收和发送缓存
    char sendbuf[256] = {0};
    char recvbuf[256] = {0};
    char symbol[4] = {0};
    char name[128] = {0}; 
    char pas1[128] = {0};
    int login_suc = 0;  // 

    while (1)  // 注册/登录循环
    {
    
        recv(client_id , recvbuf , sizeof(recvbuf) , 0);
        if(strncmp(recvbuf, "@" , 1) == 0)  // 判断是否为新注册的用户信息
        {
            sscanf(recvbuf, "%s %s %s", symbol , name, pas1);
            printf("接收到注册信息: %s \n", recvbuf);
            //把用户数据存入结构体数组中，方便管理
            user_add(client_id , name , pas1);
            printf("%s的信息已存入系统用户信息库\n", name);
            send(client_id , "注册成功!" , sizeof("注册成功!"),0);  // 注册成功发送-
            puts("");  // 换行
            memset(symbol , 0 , sizeof(symbol));
            memset(name , 0 , sizeof(name));
            memset(pas1 , 0 , sizeof(pas1));
            memset(recvbuf , 0 , sizeof(recvbuf));
        }
        else
        {
            if(login_suc == 1)  // 登录成功退出循环
            {
                break;
            }
            sscanf(recvbuf,"%s %s", name, pas1);
            printf("登陆用户: %s 密码: %s\n", name,pas1);
            for (int i = 0; i < 20; i++)  // 找用户
            {
                if(strcmp(client_ids[i].name , name) == 0)
                {
                    if(strcmp(client_ids[i].pas , pas1) == 0)
                    {
                        printf("%s上线了\n", name);
                        send(client_id,"登录成功!",sizeof("登录成功!"),0);  // 登录成功发送-
                        login_suc = 1;
                        break;
                    }
                }
            }
            if(login_suc == 0)  // 登录失败则清空name、pas和recvbuf , 进行下一次的登录 ; 登录成功则保留name用户名 , 方便下面的操作
            {
                memset(name , 0 , sizeof(name));
            }
            memset(pas1 , 0 , sizeof(pas1));
            memset(recvbuf , 0 , sizeof(recvbuf));
        }
    }

    //发送加入群聊
    char hint[256] = {0};
    strcpy(hint, name);
    strcat(hint, "加入了聊天室,");
    strcat(hint,"当前在线用户：");
    for(int n = 0;n < number;n++)
    {
        strcat(hint,client_ids[n].name);//添加名字
        strcat(hint," ");
    }
    strcat(hint,"\n");
    mass_send(hint);

    //添加消息头（名字：）
    char namehead[256] = {0};
    strcpy(namehead , name);
    strcat(namehead , ":");

    int len = 0;
    while (1)
    {
        //清空recvbuf
        bzero(recvbuf, sizeof(recvbuf));
        len = recv(client_id,recvbuf,sizeof(recvbuf),0);//接收数据到buf
        if(len <= 0)
        {
            //群发
            for (int i = 0; i < 20; i++)//找到退出的用户，清除数据
            {
                if(strcmp(client_ids[i].name,name) == 0)
                {
                    client_ids[i].cid = 0;
                    bzero(client_ids[i].name, 16);
                    break;
                }
            }
            bzero(hint, sizeof(hint));
            strcpy(hint, name);
            strcat(hint, "退出了聊天室,");
            strcat(hint,"当前在线用户：");
            for(int n = 0;n < 20;n++)
            {
                if(client_ids[n].name != NULL)
                {
                    strcat(hint,client_ids[n].name);//添加名字
                    strcat(hint," ");
                }
            }
            strcat(hint,"\n");
            mass_send(hint);
            printf("%s退出了聊天室\n", name);
            number--;
            printf("当前在线人数:%d\n",number);
    
            sleep(1);
            close(client_id);
            break;
        }
        if(strncmp(recvbuf,"@",1) == 0)
        {
            flg = 1;
        }
        /***********   私发     **********/
        if(flg == 1)
        {
            char buf1[16] = "";//@
            char buf2[16] = "";//私聊的名字
            char buf3[256] = "";//私聊的信息
            int ret = sscanf(recvbuf, "%s %s %s", buf1, buf2,buf3);
            if(ret != 3)
            {
                char error[256] ="@ 名字 要发送的消息\n";
                send(client_id,error,strlen(error),0);
            }
            else
            {
                printf("%s私聊\n",name);
                memset(sendbuf,0,256);
                strcpy(sendbuf,name);;//装入私聊发起者名字
                strcat(sendbuf,"悄悄的对你说:");//装入
                strcat(sendbuf,buf3);//包装好聊天信息
                strcat(hint,"\n");
                for (int i = 0; i < 20; i++)
                {
                    if (strcmp(client_ids[i].name,buf2) == 0)
                    {
                        send(client_ids[i].cid,sendbuf,strlen(sendbuf),0);//发送包装好的的信息
                        memset(sendbuf,0,256);
                        strcpy(sendbuf,"你悄悄的对");
                        strcat(sendbuf,client_ids[i].name);
                        strcat(sendbuf,"说:");//装入
                        strcat(sendbuf,buf3);//包装好聊天信息
                        strcat(hint,"\n");
                        send(client_id,sendbuf,strlen(sendbuf),0);
                        break;
                    }
                }
                flg = 0;
            }
            
            //printf("1.string=%s\n", recvbuf);
            //printf("1.ret=%d, buf1=%s, buf2=%s,buf3=%s\n", ret, buf1, buf2,buf3);


        }

        /***********   群发     **********/
        else
        {
            if(strncasecmp(recvbuf,"quit",4) == 0)//检测到退出，关闭套接字
            {
                printf("[%s]退出了聊天室..\n",name);
                number--;
                for (int i = 0; i < 20; i++)//找到退出的用户，清除数据
                {
                    if(strcmp(client_ids[i].name,name) == 0)
                    {
                        client_ids[i].cid = 0;
                        bzero(client_ids[i].name, 16);
                        break;
                    }
                }
                bzero(hint, sizeof(hint));
                strcpy(hint, name);
                strcat(hint, "退出了聊天室,");
                strcat(hint,"当前在线用户：");
                for(int n = 0;n < 20;n++)
                {
                    if(client_ids[n].name != NULL)
                    {
                        strcat(hint,client_ids[n].name);//添加名字
                        strcat(hint," ");
                    }
                }
                strcat(hint,"\n");
                mass_send(hint);
                printf("当前在线人数:%d\n",number);
                close(client_id);
                break;
            }
            
            memset(sendbuf,0,256);
            strcat(sendbuf,namehead);//装入名字
            strcat(sendbuf,recvbuf);//包装好聊天信息
            mass_send(sendbuf);//群发
            printf("%s\n",sendbuf);
        }
    }
    return NULL;
}
